package top.wfzzq.ds;
/**
 * java内置数据结构演示
 * 
 * @author wanghui
 *
 */

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class DsDemo {
	private static Random random = new Random();

	/**
	 * 生成演示用的数据集合
	 * 
	 * @return
	 */
	private static List<DsEntity> makeData() {
		List<DsEntity> list = new ArrayList<>();
		list.add(new DsEntity(100, "张三"));
		list.add(new DsEntity(101, "李四"));
		list.add(new DsEntity(102, "丹尼斯"));
		list.add(new DsEntity(103, "万里雪"));
		list.add(new DsEntity(104, "郑志强"));
		list.add(new DsEntity(105, "顾云昌"));
		list.add(new DsEntity(106, "李春雨"));
		list.add(new DsEntity(107, "威哥"));
		list.add(new DsEntity(108, "压模"));
		list.add(new DsEntity(109, "口服液"));
		return list;
	}

	/**
	 * 从list中随机挑选一个数据
	 * 
	 * @param List
	 * @return
	 */
	public static DsEntity rand(List<DsEntity> list) {
		// 随机数公式（上届-下届+）+下届
		if (list == null || list.isEmpty()) {
			throw new RuntimeException("集合为空");
		}
		int index = random.nextInt(list.size());
		return list.get(index);
	}

	/**
	 * 从list中随机挑选count数量的随机数据
	 * 
	 * @param list
	 *            挑选数据的数据
	 * @param count
	 *            随机数据的
	 * @return随机数据的集合
	 */
	public static List<DsEntity> rand(List<DsEntity> list, int count) {
		List<DsEntity> result = new ArrayList<>();
		if (list == null || list.isEmpty()) {
			return result;
		}
		for (int i = 0; i < count; i++) {
			int index = random.nextInt(list.size());
			result.add(list.get(index));
		}
		return result;
	}

	/**
	 * 读取文本文件中内容，统计出现胃多少个不同的字符（不包含空白字符），返回为字符串
	 * 
	 * @param textFile
	 *            文本文件路径
	 * @param sort
	 *            是否排序，false 就安照出现的次序排列，true就按照字符排序规则排序
	 * @return 出现的字符构字符串
	 * @throws Exception
	 */
	public static String countText(String textFile, boolean sort) throws Exception {
		// 读取文本方法的最佳对象
		Scanner scanner = new Scanner(new File(textFile), "UTF-8");
		// 可变字符串 当字符串拼接过多的时候因该使用该对象，否则可能造成内存溢出
		StringBuilder sb = new StringBuilder();

		// 以行为单位读取字符流，hasNextLine判断是否还有一行数据
		while (scanner.hasNextLine()) {
			// nextLine读取一行字符串
			System.out.println(scanner.nextLine());
		}
		// 将可变字符串转换为字符串对象
		String content = sb.toString();
		scanner.close();
		// System.out.println(content);
		// 正则替换所有空白字符
		content = content.replaceAll("\\s", "");
		// 去掉重复字符（Set集合不可以添加重复的数据，相同的只会添加一次）
		// hashset是默认的实现;
		// TreeSet会自动排序，LinkedHashSet会记住添加的次序
		Set<Character> set = sort ? new TreeSet<>() : new LinkedHashSet<>();// new HashSet<>();
		// 分割成字符的数组
		char[] chars = content.toCharArray();
		for (char c : chars) {
			set.add(c);
		}
		// 将set中的数据连接成String
		sb = new StringBuilder();
		for (char c : set) {
			sb.append(c);
		}
		return sb.toString();
	}

	/**
	 * 统计文本文件中出现的字符以及对应的数量（不包括空白字符）
	 * 
	 * @param textFile
	 * @param sort
	 * @return
	 * @throws Exception
	 */
	public static Map<Character, Integer> countTextNumber(String textFile, boolean sort) throws Exception {
		// map数据结构是键值对，放入数据是一对，通过key可以找到对应的值
		// 给你是个数，统计奇数量，不能是判断语句
		Map<Character, Integer> map = new HashMap<>();
		// 读取文件到string
		Scanner scanner = new Scanner(new File(textFile));
		StringBuilder sb = new StringBuilder();
		while (scanner.hasNextLine()) {
			sb.append(scanner.nextLine());

		}
		scanner.close();
		String content=sb.toString().replaceAll("\\s", "");
		//统计并计数
		//set不允许重复值，Map就是键值对，list快速随机下标访问，记住添加次序
		//Stack先进后出Queue先进先出
		//byte short int long float double boolean char String 
		//统计并计数
		char[] chars=content.toCharArray();
		//如果数据是a1ac2cb
		//1:a a在map不存在put a,1 a:1
		//2:1 1在map不存在put 1,1 a:1 ,1:1
		//3:a a在map存在get a=1+1=2 a:2,1:1
		//...
		//map.put(key .value):添加键值对数据
		//value=map.get(key):获取key对应的数据
		//map.containsKey(key):检查key是否存在
		//map.entrySet:获取map的值，结构是Map.Entry
		//   Map.Entry.getKey 获取key,Map.Entry.getValue 获取值
		//map.keySet:获取键的set集合
		//map.values:获取值的集合（很少使用，因为值可以通过key获取到）
		for(char c:chars) {
			//如果map中没有c对应的数据，那么就将C和数量1为一组添加到map中
			//containKey就是判断c是否在map的key中存在
			if (!map.containsKey(c)) {
				map.put(c, 1);
				
			} else {
              //如果map中存在对应的数据，就将数量取回来加1再放回去
				int count=map.get(c)+1;
				map.put(c, count);
			}
		}
		return map;
	}

	public static void main(String[] args) {
		try {
			Map<Character, Integer> map=countTextNumber("demo.txt", false);
			//map循环是键值对一组
			for (Map.Entry<Character, Integer> kv:map.entrySet()) {
			System.out.println(kv.getKey()+"==>"+kv.getValue());
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
//		List<DsEntity> list = makeData();
//		System.out.println(rand(list));
//		System.out.println(rand(list));
//		System.out.println(rand(list));
//		System.out.println("=========================");
//		List<DsEntity> randList = rand(list, 3);
//		// foreach循环（一次获取一笔仅向前胡迭代）
//		// for(集合或数组中的数据类型 每次循环得到变量：集合或者数组)
//		for (DsEntity dsEntity : randList) {
//			System.out.println(dsEntity);
//		}
//		System.out.println("=========================");
//		try {
//			System.out.println(countText("demo.txt", false));
//			System.out.println(countText("demo.txt", true));
//		} catch (Exception ex) {
//			ex.printStackTrace();
//		}
		// System.out.println("==========================");
		// long start=System.currentTimeMillis();//当前时间戳
		// Random r=new Random();
		// Set<Integer> sets=new TreeSet<>();
		// for (int i = 0; i < 10000000; i++) {
		// sets.add(r.nextInt(10000000));
		// }
		// System.out.println(sets.size());
		// System.out.println("时间消耗 （毫秒）"+(System.currentTimeMillis()-start));
	}
}
